#!/usr/bin/env python

import os
import sys
import re
import db
from db import *
from plotchart import PlotChart
import numpy as np
from os.path import join as joinpath
from dbstat import DbStat

def usage():
    print '''\
Usage: %s -c <configuration-file>
''' % sys.argv[0]
    sys.exit(1)

def getopts(list, flags):
    import getopt
    try:
        opts, args = getopt.getopt(list, flags)
    except getopt.GetoptError:
        usage()

    return opts, args

work_dir = 'spec_workdir'
home = os.environ['HOME']

output_dir = os.path.join(home, work_dir, 'figs')

int_benchmarks = ['gzip_graphic','vpr_route','gcc_166','mcf',
                  'perlbmk_makerand',
                  'crafty','parser_spec','gap','vortex_2',
                  'bzip2_program','twolf',]

float_benchmarks = ['wupwise','swim',
                    'mgrid','applu','mesa','art_110',
                    'equake','ammp','apsi'] 

def GeometryMean(X):

   return exp(sum([log(x) for x in X]) / len(X))

def ArithmaticMean(X):

    return float(sum([float(x) for x in X]) / float(len(X)))

class Options:pass

if __name__ == '__main__':
    import getpass

    source = db.Database()
    source.host = '202.118.229.70'
    source.db = 'pengfei'
    source.user = 'pengfei'
    source.passwd = '83658365yy'

    try:
        source.connect()
    except:
        raise AttributeError, 'Cannot connect to db'

    options = Options()
    options.conf = None
   
    opts, args = getopts(sys.argv[1:],'-c:')

    for o,a in opts:
        if o == '-c':
            options.conf = a

    if not options.conf :
        sys.exit('Where is your configuration file?')

    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)

    print 'Put figures to %s' % output_dir

    for line in open(options.conf) :
        drawing_options = line.split()

        draw = False

        if not drawing_options or drawing_options[0] != '!' :
            continue

        if drawing_options[1] == 'SSMP':

            statistics = drawing_options[2]
            base_stat_name = statistics
            benchmark_hint = drawing_options[3]
            configurations = drawing_options[4]
            comments = drawing_options[5]

            configurations = configurations.split(',')

            if len(statistics.split(',')) > 1:
                sys.exit('Only one statitics is supported in SSMP mode')

            comments = comments.split(',')

            stat_mode = comments[2]

            stat_step = 1

            chart = PlotChart()

            if comments[0] == 'inc' or comments[0] == 'powerof2':
                if len(comments) < 5:
                    sys.exit('''SSMP option need 5 comments seperated by
                        comma, the first one is the key word 'inc or
                        powerof2',
                        the second one is the starting number, the
                        third is the ending number, the fourth is the
                        incremental step, and the final one is the
                        statistic name''')
                else:
                    stat_start = int(comments[1])
                    stat_end = int(comments[2])
                    stat_step = int(comments[3])
                    stat_name = comments[4]
                    
                    temp_confs = []
                    for conf in configurations:
                        if comments[0] == 'inc':
                            temp_confs.extend([conf + '_' + stat_name +\
                            '_' + str(i) for i in range(stat_start, stat_end,\
                                stat_step)])
                        elif comments[0] == 'powerof2':
                            temp_confs.extend([conf + '_' + stat_name +\
                            '_' + str(2**i) for i in range(stat_start, stat_end,\
                                stat_step)])

                    configurations = temp_confs

                    chart.xticks = [str(i) for i in range(stat_start,\
                        stat_end, stat_step)]

                    print chart.xticks

            elif len(comments) != conf_num:
                sys.exit('''SSMP option need %d comments seperated by
                        comma''' % conf_num)

            benchmarks = []
            if benchmark_hint == 'all':
                benchmarks = int_benchmarks + float_benchmarks 
            elif benchmark_hint == 'int':
                benchmarks = int_benchmarks
            elif benchmark_hint == 'fp':
                benchmarks = float_benchmarks 
            else :
                benchmarks = benchmark_hint.split(',')

            conf_num = len(configurations)

            data = np.zeros(len(benchmarks) * conf_num)
            extra = np.zeros(len(benchmarks) * conf_num)
            
            data.shape = (len(benchmarks), conf_num)
            extra.shape = (len(benchmarks), conf_num)

            chart.legend = []
            chart.xlabel = comments[-1].replace('_', ' ')
            chart.ylabel = comments[-2].replace('_', ' ')

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)


            for i,bench in enumerate(benchmarks):

                for j,conf in enumerate(configurations):

                    if statistics == 'mpki':
                        mispredicts = DbStat(source, bench,
                                'system.cpu.commit.branchMispredicts', 
                                conf)
                        commit_insts = DbStat(source, bench,
                                'system.cpu.committedInsts_total',
                                conf)
                        data[i,j] = mispredicts.data() /\
                            (commit_insts.data() / 1000.0)
                    elif statistics == 'mpki_type':
                        mispredicts = DbStat(source, bench,
                                'system.cpu.commit.branchTypeMispredicts::0', 
                                conf)
                        commit_insts = DbStat(source, bench,
                                'system.cpu.committedInsts_total',
                                conf)
                        data[i,j] = mispredicts.data() /\
                            (commit_insts.data() / 1000.0)
 
                    else:
                        stat = DbStat(source, bench, statistics, conf)
                        data[i,j] = stat.data()

                chart.legend.append(bench)

            draw = True
            
        if drawing_options[1] == 'SMSP':

            base_stat_name = drawing_options[2]
            benchmark_hint = drawing_options[3]
            configurations = drawing_options[4]
            comments = drawing_options[5]

            configurations = configurations.split(',')

            if len(configurations) != 1:
                sys.exit('''SMSP option only support just ONE configuration, no
                        more, no less''')
            
            comments = comments.split(',')

            if len(comments) != 3 :
                sys.exit('''SMSP option need three comments seperated by comma''')

            stat_step = int(comments[0])
            stat_number = int(comments[1])
            stat_mode = comments[2]

            benchmarks = []
            if benchmark_hint == 'all' :
                benchmarks = all_benchmarks
            else :
                benchmarks = benchmark_hint.split(',')

            data = np.zeros(len(benchmarks)*stat_number)
            extra = np.zeros(len(benchmarks)*stat_number)
            
            data.shape = (len(benchmarks),stat_number)
            extra.shape = (len(benchmarks),stat_number)

            chart = PlotChart()
            chart.legend = []
            chart.xlabel = base_stat_name
            chart.ylabel = stat_mode

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)

            for i,bench in enumerate(benchmarks):

                for j in range(len(data[i])):
                    if j != len(data[i])-1:
                        stat_name = base_stat_name + '::' + '%d-%d' % (j*stat_step,
                            (j+1)*stat_step)
                    else :
                        stat_name = base_stat_name + '::' + '%d' % (j*stat_step)

                    stat = DbStat(source, bench, stat_name, configurations[0])
                    data[i,j] = stat.data()
                
                chart.legend.append(bench)

            draw = True

        if drawing_options[1] == 'SSMPA':

            statistics = drawing_options[2]
            base_stat_name = statistics
            benchmark_hint = drawing_options[3]
            configgroups = drawing_options[4]
            comments = drawing_options[5]

            configgroups = configgroups.split(',')

            if len(statistics.split(',')) > 1:
                sys.exit('Only one statitics is supported in SSMP mode')

            comments = comments.split(',')

            stat_mode = comments[2]

            stat_step = 1

            chart = PlotChart()
            chart.xticks = comments

            configurations = []
            subconf_num = 0
            if comments[0] == 'inc' or comments[0] == 'powerof2':
                if len(comments) < 5:
                    sys.exit('''SSMPA option need 5 comments seperated by
                        comma, the first one is the key word 'inc or
                        powerof2',
                        the second one is the starting number, the
                        third is the ending number, the fourth is the
                        incremental step, and the final one is the
                        statistic name''')
                else:
                    stat_start = int(comments[1])
                    stat_end = int(comments[2])
                    stat_step = int(comments[3])
                    stat_suffix = comments[4]

                    if stat_suffix == 'NON':
                        stat_suffix = ''

                    subconf_num = stat_end - stat_start + 1
                    
                    temp_confs = []
                    for conf in configgroups:
                        if comments[0] == 'inc':
                            temp_confs.append([conf + '_' + str(i) + \
                                stat_suffix for i in\
                                range(stat_start, stat_end + 1, stat_step)])

                            chart.xticks = [str(i) + stat_suffix for i in\
                                    range(stat_start, stat_end + 1, stat_step)]
                        elif comments[0] == 'powerof2':
                            temp_confs.append([conf + '_' + str(2**i)\
                                + stat_suffix for i in \
                                range(stat_start, stat_end + 1, stat_step)])

                            chart.xticks = [str(2**i) + stat_suffix for i in\
                                    range(stat_start, stat_end + 1, stat_step)]

                    configurations = temp_confs

                    print chart.xticks

            else:
                sys.exit('''SSMPA need keyword of inc or powerof2''')

            benchmarks = []
            if benchmark_hint == 'all' :
                benchmarks = int_benchmarks + float_benchmarks 
            elif benchmark_hint == 'int':
                benchmarks = int_benchmarks
            elif benchmark_hint == 'fp':
                benchmarks = float_benchmarks 
            else :
                benchmarks = benchmark_hint.split(',')

            confgroup_num = len(configgroups)

            data = np.zeros(confgroup_num * subconf_num)
            extra = np.zeros(confgroup_num * subconf_num)
            
            data.shape = (confgroup_num, subconf_num)
            extra.shape = (confgroup_num, subconf_num)

            chart.legend = comments[5:5 + confgroup_num]
            chart.xlabel = comments[-1].replace('_', ' ')
            chart.ylabel = comments[-2].replace('_', ' ')

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)


            for i,conf in enumerate(configurations):

                for j,subconf in enumerate(conf):

                    print subconf

                    temp_data = np.zeros(len(benchmarks))

                    for k,bench in enumerate(benchmarks):

                        if statistics == 'mpki':
                            mispredicts = DbStat(source, bench,
                                    'system.cpu.commit.branchMispredicts', 
                                    subconf)
                            commit_insts = DbStat(source, bench,
                                    'system.cpu.committedInsts_total',
                                    subconf)
                            temp_data[k] = mispredicts.data() /\
                                (commit_insts.data() / 1000.0)

                    data[i,j] = ArithmaticMean(temp_data)

            draw = True

            configurations[0] = configgroups[0]
 
        if draw:
            chart.data = data
            chart.legend_size = 6
            chart.figure_size = [0.09,0.14,0.73,0.7]
            chart.chart_size = [4,2.625]
            chart.xlabel_rotation = 30
            chart.colormap = 'jet'
            chart.ygrid = True
            chart.graph()

            fname = re.sub(':','--',base_stat_name)
            fname = re.sub('\.','-',fname)
            fname = fname + '-' + configurations[0] + '-'\
                    + re.sub(',', '-', benchmark_hint) 
                            
            png_dir = joinpath(output_dir, 'png')
            pdf_dir = joinpath(output_dir, 'pdf')
            eps_dir = joinpath(output_dir, 'eps')
            ps_dir = joinpath(output_dir, 'ps')
            csv_dir = joinpath(output_dir, 'csv')

            if not os.path.isdir(png_dir):
                os.makedirs(png_dir)

            if not os.path.isdir(pdf_dir):
                os.makedirs(pdf_dir)

            if not os.path.isdir(eps_dir):
                os.makedirs(eps_dir)

            if not os.path.isdir(ps_dir):
                os.makedirs(ps_dir)

            if not os.path.isdir(csv_dir):
                os.makedirs(csv_dir)

            chart.savefig(joinpath(png_dir, fname + '.png'))
            chart.savefig(joinpath(pdf_dir, fname + '.pdf'))
#            chart.savefig(joinpath(eps_dir, fname + '.eps'))
#            chart.savefig(joinpath(ps_dir, fname + '.ps'))
            chart.savecsv(joinpath(csv_dir, fname + '.csv'))

